7  bulkTCRseq: IMP-expanded clones Repertoire Fraction

7.1 Set up workspace

# Libraries
library(dplyr)

Attaching package: 'dplyr'
The following objects are masked from 'package:stats':

    filter, lag
The following objects are masked from 'package:base':

    intersect, setdiff, setequal, union
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ forcats   1.0.0     ✔ readr     2.1.5
✔ ggplot2   3.5.1     ✔ stringr   1.5.1
✔ lubridate 1.9.4     ✔ tibble    3.2.1
✔ purrr     1.0.4     ✔ tidyr     1.3.1
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(Seurat)
Loading required package: SeuratObject
Loading required package: sp

Attaching package: 'SeuratObject'

The following objects are masked from 'package:base':

    intersect, t
library(ggvenn)
Loading required package: grid
library(ggridges)

7.2 Load patient colors

pt_cols <- readRDS("Part0_Patient_Color.rds")
pt_fill <- readRDS("Part0_Patient_Fill.rds")

7.3 Open bulkTCR typed clones

p101_betas_typed <- read.csv("p101_betas_merged_typed_Part3.csv")
p103_betas_typed <- read.csv("p103_betas_merged_typed_Part3.csv")
p104_betas_typed <- read.csv("p104_betas_merged_typed_Part3.csv")
p105_betas_typed <- read.csv("p105_betas_merged_typed_Part3.csv")
p106_betas_typed <- read.csv("p106_betas_merged_typed_Part3.csv")
p108_betas_typed <- read.csv("p108_betas_merged_typed_Part3.csv")
p109_betas_typed <- read.csv("p109_betas_merged_typed_Part3.csv")
p110_betas_typed <- read.csv("p110_betas_merged_typed_Part3.csv")
p111_betas_typed <- read.csv("p111_betas_merged_typed_Part3.csv")

betas_typed <- list(p101_betas_typed = p101_betas_typed,
                    p103_betas_typed = p103_betas_typed,
                    p104_betas_typed = p104_betas_typed,
                    p105_betas_typed = p105_betas_typed,
                    p106_betas_typed = p106_betas_typed,
                    p108_betas_typed = p108_betas_typed,
                    p109_betas_typed = p109_betas_typed,
                    p110_betas_typed = p110_betas_typed,
                    p111_betas_typed = p111_betas_typed)

7.4 Compare the distribution of IMP-expanded vs non-expanded clones

# Collect the columns of interest and rename
select_postvax_cols <- function(df){
  postvax <- df[,grep(".*postvax($|_umi)", colnames(df))]
  colnames(postvax) <- c("postvax_freq", "postvax_umi")
  df <- df[, c("Beta_clonotype", "Type", "Patient", "expanded_local_min")]
  df <- cbind(df, postvax)
  return(df)
}

postvax_tp.list <- lapply(betas_typed, select_postvax_cols)

postvax_tp <- do.call(rbind, postvax_tp.list)

7.5 Plot the frequency of IMP-expanded clones after vaccination for Fig 3H middle

p1 <- postvax_tp %>%
  filter(expanded_local_min == TRUE) %>% 
  mutate(Patient = factor(Patient, levels = c("P101", "P104", "P109", "P108", "P105", "P111", "P106", "P110", "P103"))) %>%
  ggplot(aes(x = postvax_freq, y = Patient, fill = Patient)) +
  geom_density_ridges(alpha = 0.5, scale = 1) +
  scale_x_log10() +
  pt_fill +
  theme_classic() +
  xlab("Frequency of IMP-expanded \nclones after vaccination\n")

n_expanded_postvax <- postvax_tp %>%
  filter(expanded_local_min == TRUE) %>%
  group_by(Patient) %>%
  dplyr::count() %>%
  mutate(Patient = factor(Patient, levels = c("P101", "P104", "P109", "P108", "P105", "P111", "P106", "P110", "P103")),
         x = 0.08,
         n = paste0("n=",n))

p1 + geom_text(data = n_expanded_postvax, 
              aes(y = as.numeric(Patient) + 0.1, x = x, label = n),
              position=position_nudge(y= .25), 
              colour="black", 
              size=3.5)
Picking joint bandwidth of 0.111

7.6 Plot clonal dominance of IMP-expanded clones after vaccination for Fig 3H right

fct_expanded <- postvax_tp %>%
  group_by(Patient, expanded_local_min, Type) %>%
  summarize(sum = sum(postvax_freq)) %>%
  pivot_wider(names_from = "expanded_local_min", values_from = sum) %>%
  dplyr::rename("Nonexpanded" = "FALSE",
                "Expanded" = "TRUE") %>%
  replace(is.na(.), 0) %>%
  mutate(fct_expanded = Expanded/(Expanded+Nonexpanded))
`summarise()` has grouped output by 'Patient', 'expanded_local_min'. You can
override using the `.groups` argument.
fct_expanded %>%
  group_by(Type) %>%
  summarize(median(fct_expanded)*100)
# A tibble: 3 × 2
  Type           `median(fct_expanded) * 100`
  <chr>                                 <dbl>
1 Existing                              0.435
2 Post-Nivolumab                        0.327
3 Post-Vaccine                         40.8  
p2 <- fct_expanded %>%
  mutate(Patient = factor(Patient, levels = c("P103", "P110" , "P106" , "P111" , "P105" , "P108", "P109" , "P104", "P101"))) %>%
  ggplot(aes(x = fct_expanded, y = Type, fill = Type)) +
  geom_col(color = "#920000FF", size = 1) +
  facet_wrap(facets = ~factor(Patient, ), ncol = 1, strip.position = "right") +
  scale_x_continuous(breaks=c(0, 0.5)) +
  scale_y_discrete(expand = c(0.5, 0)) +
  ylab("Fraction of the repertoire after vaccination") +
  xlab("Fraction of the repertoire\nafter vaccination") +
  theme_classic() +
  scale_fill_manual(values = c("#B3B3B3", "#CD950C", "#0072B2"), name = "Type of IMP-\nexpanded clone") +
  theme(axis.title=element_text(size=10),
        axis.ticks.y = element_blank(),
        axis.text.y = element_blank())
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
ℹ Please use `linewidth` instead.
p2

7.7 Get session info

sessionInfo()
R version 4.3.2 (2023-10-31)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Rocky Linux 8.10 (Green Obsidian)

Matrix products: default
BLAS/LAPACK: /usr/lib64/libopenblasp-r0.3.15.so;  LAPACK version 3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=en_US.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=en_US.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C       

time zone: America/New_York
tzcode source: system (glibc)

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
 [1] ggridges_0.5.6     ggvenn_0.1.10      Seurat_5.1.0       SeuratObject_5.0.2
 [5] sp_2.2-0           lubridate_1.9.4    forcats_1.0.0      stringr_1.5.1     
 [9] purrr_1.0.4        readr_2.1.5        tidyr_1.3.1        tibble_3.2.1      
[13] ggplot2_3.5.1      tidyverse_2.0.0    dplyr_1.1.4       

loaded via a namespace (and not attached):
  [1] deldir_2.0-4           pbapply_1.7-2          gridExtra_2.3         
  [4] rlang_1.1.5            magrittr_2.0.3         RcppAnnoy_0.0.22      
  [7] spatstat.geom_3.3-2    matrixStats_1.5.0      compiler_4.3.2        
 [10] png_0.1-8              vctrs_0.6.5            reshape2_1.4.4        
 [13] pkgconfig_2.0.3        fastmap_1.2.0          utf8_1.2.4            
 [16] promises_1.3.2         rmarkdown_2.29         tzdb_0.5.0            
 [19] xfun_0.50              jsonlite_1.8.9         goftest_1.2-3         
 [22] later_1.4.1            spatstat.utils_3.1-0   irlba_2.3.5.1         
 [25] parallel_4.3.2         cluster_2.1.8.1        R6_2.6.1              
 [28] ica_1.0-3              spatstat.data_3.1-2    stringi_1.8.4         
 [31] RColorBrewer_1.1-3     reticulate_1.42.0      spatstat.univar_3.0-0 
 [34] parallelly_1.41.0      lmtest_0.9-40          scattermore_1.2       
 [37] Rcpp_1.0.14            knitr_1.49             tensor_1.5            
 [40] future.apply_1.11.3    zoo_1.8-13             sctransform_0.4.1     
 [43] httpuv_1.6.15          Matrix_1.6-5           splines_4.3.2         
 [46] igraph_2.0.3           timechange_0.3.0       tidyselect_1.2.1      
 [49] abind_1.4-8            rstudioapi_0.17.1      spatstat.random_3.3-1 
 [52] spatstat.explore_3.3-2 codetools_0.2-20       miniUI_0.1.1.1        
 [55] listenv_0.9.1          lattice_0.22-7         plyr_1.8.9            
 [58] shiny_1.9.1            withr_3.0.2            ROCR_1.0-11           
 [61] evaluate_1.0.1         Rtsne_0.17             future_1.34.0         
 [64] fastDummies_1.7.5      survival_3.8-3         polyclip_1.10-7       
 [67] fitdistrplus_1.2-2     pillar_1.10.1          KernSmooth_2.23-26    
 [70] plotly_4.10.4          generics_0.1.3         RcppHNSW_0.6.0        
 [73] hms_1.1.3              munsell_0.5.1          scales_1.3.0          
 [76] globals_0.16.3         xtable_1.8-4           glue_1.8.0            
 [79] lazyeval_0.2.2         tools_4.3.2            data.table_1.15.4     
 [82] RSpectra_0.16-2        RANN_2.6.2             leiden_0.4.3.1        
 [85] dotCall64_1.2          cowplot_1.1.3          colorspace_2.1-1      
 [88] nlme_3.1-168           patchwork_1.3.0        cli_3.6.3             
 [91] spatstat.sparse_3.1-0  spam_2.11-1            viridisLite_0.4.2     
 [94] uwot_0.2.3             gtable_0.3.6           digest_0.6.37         
 [97] progressr_0.15.1       ggrepel_0.9.5          htmlwidgets_1.6.4     
[100] farver_2.1.2           htmltools_0.5.8.1      lifecycle_1.0.4       
[103] httr_1.4.7             mime_0.13              MASS_7.3-60.0.1